/***************************************************************************//**
 * @file app_device.c
 * @brief for device attributes，参数数据管理，考虑将更改频次少的、长度大的 字段放入NVM以节省内存
 * @brief 该h文件处于很底层 可被所有其他层次mac network、app层次的函数包含使用
 * @author ze 
 * @date  2022/7/03.
 * @copyright Copyright 
 ******************************************************************************/
#include "device.h"
#include "string.h"
#include "bsp_nvm.h"
#include "bsp_system.h"
#include "util.h"
#include "net_rolling_code.h"
#include "net_protocol.h"
#include "app_api.h"
#include "app_log.h"
#include "device_nvm.h"
#include "net_register.h"
#include "net_packet.h"
#include "mac_TDMA.h"
#include "mac_timeSync.h"
#include "device_type.h"
#ifdef HUB_DEVICE
typedef struct{
  uint8_t evt_a0_tns;
  uint8_t evt_a1_tns;
  uint8_t evt_a2_tns;
  uint8_t evt_a0_flag;
  uint8_t evt_a1_flag;
  uint8_t evt_a2_flag;
  uint8_t hub_usart_seq;
  uint8_t panel_usart_seq;
  uint8_t bcast_busy;
  uint8_t cfg_req;
  uint8_t freq;
  uint8_t jamming;
  uint8_t custcode;
  uint8_t reset_mode;
  uint8_t led_ctrl_flag[NODE_MAX_COUNT]; //1-254
  uint8_t operate_ctrl_flag[NODE_MAX_COUNT]; //1-254
  //uint8_t keyvalue_get_flag[NODE_MAX_COUNT]; //1-254
  uint8_t led_ctrl[NODE_MAX_COUNT][LEDCTRL_LENGTH]; //1-254
  uint8_t operate_ctrl[NODE_MAX_COUNT][OPERATECTRL_LENGTH];//1-254
  //uint8_t keyvalue_get[NODE_MAX_COUNT][GETKEYVALUE_LENGTH]; //1-254
  uint8_t ota_consult_flag[NODE_MAX_COUNT]; //1-254
  DEVICE_SOURCE_TYPE_EN mac_src;
  uint8_t mac[NODE_MAX_COUNT][MAC_ADDRESS_LENGTH];
  DEVICE_SOURCE_TYPE_EN node_join_info_src;
  uint8_t node_join_info[NODE_JOIN_INFO_LENGTH];
  uint8_t register_ctrl;
  uint8_t register_mac[MAC_ADDRESS_LENGTH];
  uint8_t register_qr[16];
  uint8_t register_sn[SN_LENGTH];
  uint8_t enable_retrans;
  int8_t real_rssi;
  int8_t avg_rssi;
  uint8_t ota_panelsetmode;
  uint8_t ota_panelsetnum;
  uint8_t ota_panelsetid[OTA_ID_BUF_MAX]; //单次最多升级128个
  uint8_t delay_txtask;
  uint8_t IOen_lock[DEVICE_TYPE_IO_CN]; //0-127
  int8_t  rssi_limit;
  uint8_t qrfr1_buf[NODE_MAX_COUNT];
  uint8_t qrfr2_buf[NODE_MAX_COUNT];
  uint8_t qrfh1_buf[NODE_MAX_COUNT];
  uint8_t qrfh2_buf[NODE_MAX_COUNT];
  uint8_t opption_buf[NODE_MAX_COUNT][OPTION_LENGTH];
  uint8_t join_pub_lock[NODE_JOIN_PUB_LENGTH];
}device_ram_t;

device_ram_t ram_attr = {0};
uint8_t qrfh_countdown[NODE_MAX_COUNT] = {0};
#else
typedef struct
{
  uint8_t qrfH1;
  uint8_t qrfH2;
  uint8_t qrfR1;
  uint8_t qrfR2;
}rfm_ram_t;
rfm_ram_t rfm_ram = {0};
#endif

typedef struct{
  uint8_t file_type;
  uint8_t request_flag;
  uint8_t request_value[OTA_REQUEST_VALUE_LENGTH];
  uint8_t confirm_flag;
  uint8_t confirm_value[OTA_CONFIRM_VALUE_LENGTH];
  uint8_t consult_value[OTA_CONSULT_KEYVALUE_LENGTH];
  uint8_t updateme_id[OTA_ID_BUF_MAX];
  uint8_t updateme_id_num;
  //uint8_t updateme_order_num;
  uint8_t read_link_idx;
  uint8_t write_link_idx;
}file_ram_t;
file_ram_t file_ram = {0};

hardinfo_t hard_info={0};

uint8_t log_enable[4] = {0};

#if defined(CONFIG_RF_FREQ_868)
static RF_FREQ_EN eRfFreq = RF_FREQ_868MHZ; //默认868MHz
#elif defined(CONFIG_RF_FREQ_915)
static RF_FREQ_EN eRfFreq = RF_FREQ_915MHZ; //默认915MHz
#elif defined(CONFIG_RF_FREQ_433)
static RF_FREQ_EN eRfFreq = RF_FREQ_433MHZ; //433MHz
#elif defined(CONFIG_RF_FREQ_915_RCM)
static RF_FREQ_EN eRfFreq = RF_FREQ_915MHZ_RCM;
#elif defined(CONFIG_RF_FREQ_868_WPC)
static RF_FREQ_EN eRfFreq = RF_FREQ_868MHZ_WPC;
#else
"error:No define RF_FREQ in config.h"
#endif

#ifdef SPVN_TIME_DEFAULT_1MIN
static SPVN_TIME_EN eSpvnTime =SPVN_TIME_1MIN;
#else
static SPVN_TIME_EN eSpvnTime =SPVN_TIME_5MIN;
#endif

SPVN_TIME_EN getDeviceSpvnTime()
{
  return eSpvnTime;
}

void setDeviceSpvnTime(SPVN_TIME_EN spvnT)
{
  if(spvnT > SPVN_TIME_MAX)
    {
      return;
    }
  if(eSpvnTime == spvnT)
    {
      return;
    }
  eSpvnTime = spvnT;
  spvnSlotInit();
  startSpvnTimer(1); //
  printf("set spvn time %d\r\n",eSpvnTime);
}

RF_FREQ_EN getDeviceRfFreq()
{
  return eRfFreq;
}

void printfDeviceRfFreqInfo()
{
  if(eRfFreq == RF_FREQ_868MHZ){
      printf("frequency band : 868MHz\r\n");
  }else if(eRfFreq == RF_FREQ_915MHZ){
      printf("frequency band : 915MHz\r\n");
  }else if(eRfFreq == RF_FREQ_433MHZ){
      printf("frequency band : 433MHz\r\n");
  }else if(eRfFreq == RF_FREQ_915MHZ_RCM){
      printf("frequency band : RCM 915\r\n");
  }else if(eRfFreq == RF_FREQ_868MHZ_WPC){
      printf("frequency band : WPC 868\r\n");
  }else{
      printf("frequency band : unknown\r\n");
  }
}

void setDeviceRfFreq(RF_FREQ_EN freq)
{
  if(freq >= RF_FREQ_MAX)
  {
    return;
  }
  if(eRfFreq == freq){
      return;
  }
  eRfFreq = freq;
  DS_nvmWrite(ENbyKeyRfReq, &eRfFreq, 1);
  printf("set rf freq %d\r\n",eRfFreq);
  //NVIC_SystemReset(); 等给panel应答之后再软复位
}

void device_param_init(void)
{

}

int setThisParam(DEVICE_ATTRIBUTE_EN attr, void* pData)
{
    if(!pData){
       return -1;
    }
    int iret = 0;
    switch(attr){
#ifdef HUB_DEVICE
        case ENbyEvtA0TNS:
          memcpy((char *)&ram_attr.evt_a0_tns, pData, 1);
          break;
        case ENbyEvtA1TNS:
          memcpy((char *)&ram_attr.evt_a1_tns, pData, 1);
          break;
        case ENbyEvtA2TNS:
          memcpy((char *)&ram_attr.evt_a2_tns, pData, 1);
          break;
        case ENbyEvtA0AckFlag:
          memcpy((char *)&ram_attr.evt_a0_flag, pData, 1);
          break;
        case ENbyEvtA1AckFlag:
          memcpy((char *)&ram_attr.evt_a1_flag, pData, 1);
          break;
        case ENbyEvtA2AckFlag:
          memcpy((char *)&ram_attr.evt_a2_flag, pData, 1);
          break;
        case ENbyHubUsartSeq:
          memcpy((char *)&ram_attr.hub_usart_seq, pData, 1);
          break;
        case ENbyPanelUsartSeq:
          memcpy((char *)&ram_attr.panel_usart_seq, pData, 1);
          break;
        case ENbyBcastBusy:
          memcpy((char *)&ram_attr.bcast_busy, pData, 1);
          break;
        case ENbyCfgReq:
          memcpy((char *)&ram_attr.cfg_req, pData, 1);
          break;
        case ENbyFreq:
          memcpy((char *)&ram_attr.freq, pData, 1);
          break;
        case ENbyjamming:
          memcpy((char *)&ram_attr.jamming, pData, 1);
          break;
        case ENbycustcode:
          memcpy((char *)&ram_attr.custcode, pData, 1);
          break;
        case ENbyLocalRegister:
          memcpy((char *)&ram_attr.register_ctrl, pData, 1);
          if(ram_attr.register_ctrl){
              memset(ram_attr.join_pub_lock, 0, NODE_JOIN_PUB_LENGTH);
          }
          break;
        case ENbyRegisterMAC:
          memcpy((char *)&ram_attr.register_mac, pData, MAC_ADDRESS_LENGTH);
          break;
        case ENbyRegisterQrKey:
          memcpy((char *)&ram_attr.register_qr, pData, 16);
          break;
        case ENbyRegisterSN:
          memcpy((char *)&ram_attr.register_sn, pData, SN_LENGTH);
          break;
        case ENbyResetMode:
          memcpy((char *)&ram_attr.reset_mode, pData, 1);
          break;
        case ENbyEnableRetrans:
          memcpy((char *)&ram_attr.enable_retrans, pData, 1);
          break;
        case ENbyRealRssi:
          memcpy((char *)&ram_attr.real_rssi, pData, 1);
          break;
        case ENbyAvgRssi:
          memcpy((char *)&ram_attr.avg_rssi, pData, 1);
          break;
        case ENbyPanelSetOtaMode:
          memcpy((char *)&ram_attr.ota_panelsetmode, pData, 1);
          break;
        case ENbyPanelSetOtaNum:
          memcpy((char *)&ram_attr.ota_panelsetnum, pData, 1);
          break;
        case ENbyPanelSetOtaId:
          memcpy((char *)&ram_attr.ota_panelsetid, pData, OTA_ID_BUF_MAX);
          break;
        case ENbyDelayTxTask:
          memcpy((char *)&ram_attr.delay_txtask, pData, 1);
          break;
        case ENbyNodeJoinInfo:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeyNodeJoinInfo,pData, NODE_JOIN_INFO_LENGTH);

#else
          iret = DS_nvmWrite(ENbyNodeJoinInfo,pData, NODE_JOIN_INFO_LENGTH);
#endif
          memcpy(ram_attr.node_join_info,pData,NODE_JOIN_INFO_LENGTH);
          break;
#else
        case ENbyQrfH1:
          memcpy(&rfm_ram.qrfH1,pData,1);
          break;
        case ENbyQrfH2:
          memcpy(&rfm_ram.qrfH2,pData,1);
          break;
        case ENbyQrfR1:
          memcpy(&rfm_ram.qrfR1,pData,1);
          break;
        case ENbyQrfR2:
          memcpy(&rfm_ram.qrfR2,pData,1);
          break;
#endif
          /* hard info*/
        case ENpbyKeyM://sn
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeySN,pData, SN_LENGTH);

#else
          iret = DS_nvmWrite(ENpbyKeyM,pData, SN_LENGTH);
#endif
          break;
        case ENbyHardType:
#ifdef CONFIG_NVM_VERSION
          //iret = DS_nvmWrite(ENbyKeyHardType,pData, 1);

#else
          //iret = DS_nvmWrite(ENbyHardType,pData, 1);
#endif
          break;
        case ENbyModelType:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeyModelType,pData, 1);

#else
          iret = DS_nvmWrite(ENbyModelType,pData, 1);
#endif
          break;
        case ENpbyRfVer:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeyRfVer,pData, PRF_LENGTH);

#else
          iret = DS_nvmWrite(ENpbyRfVer,pData, PRF_LENGTH);
#endif
          break;
        case ENpbySensorVer:
#ifdef CONFIG_NVM_VERSION

          iret = DS_nvmWrite(ENbyKeySensorVer,pData, 3);

#else
          iret = DS_nvmWrite(ENpbySensorVer,pData, 3);
#endif
          break;
        case ENbyDeviceType:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeyDeviceType,pData, 1);

#else
          iret = DS_nvmWrite(ENbyDeviceType,pData, 1);
#endif
          break;
        case ENpbyMacID:
        //TODO:测试数据,正式mac address改为工厂烧录
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeyMacID,pData, MAC_ADDRESS_LENGTH);
#else
          iret = DS_nvmWrite(ENpbyMacID,pData, MAC_ADDRESS_LENGTH);
#endif
          break;
        case ENbyTransFileType:
          memcpy((char *)&file_ram.file_type, pData, 1);
          break;
        case ENbyOtaUpdatemeID:
          memcpy((char *)&file_ram.updateme_id, pData, OTA_ID_BUF_MAX);
          break;
        case ENbyOtaUpdatemeIDNum:
          memcpy((char *)&file_ram.updateme_id_num, pData, 1);
          break;
        //case ENbyHandShakeCount:
        //  memcpy((char *)&file_ram.handshake_count, pData, 1);
        //  break;
        case ENbyOtaRequestFlag:
          memcpy((char *)&file_ram.request_flag, pData, 1);
          break;
        case ENbyOtaRequestKeyValue:
          memcpy((char *)&file_ram.request_value, pData, OTA_REQUEST_VALUE_LENGTH); //value[len 0 ftype 1 info]
          break;
        case ENbyOtaConfirmFlag:
          memcpy((char *)&file_ram.confirm_flag, pData, 1);
          break;
        case ENbyOtaConfirmKeyValue:
          memcpy((char *)&file_ram.confirm_value, pData, OTA_CONFIRM_VALUE_LENGTH); //value[len 0 ftype 1 info]
          break;
        case ENbyOtaConSultKeyValue:
          memcpy((char *)&file_ram.consult_value, pData, OTA_CONSULT_KEYVALUE_LENGTH); //key[0] value[len 1 ctrl 2 ftype 3 size 4-7 pagesize 8 sha256 9-40]
          break;
        case ENbyReadFileLinkIdx:
          memcpy((char *)&file_ram.read_link_idx, pData, 1);
          break;
        case ENbyWriteFileLinkIdx:
          memcpy((char *)&file_ram.write_link_idx, pData, 1);
          break;
        case ENpbySystemID:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeySystemID,pData, 3);

#else
          iret = DS_nvmWrite(ENpbySystemID,pData, 3);
#endif
          break;
        case ENpbyKeyA:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeyKeyA,pData, KEY_MAX_LENGTH);

#else
          iret = DS_nvmWrite(ENpbyKeyA,pData, KEY_MAX_LENGTH);
#endif
        break;
        case ENpbyKeyB:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeyKeyB,pData, KEY_MAX_LENGTH);

#else
          iret = DS_nvmWrite(ENpbyKeyB,pData, KEY_MAX_LENGTH);
#endif
          break;
        case ENpbySystemKey:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeySystemKey,pData, KEY_MAX_LENGTH);

#else
          iret = DS_nvmWrite(ENpbySystemKey,pData, KEY_MAX_LENGTH);
#endif
          break;
        case ENpbyBroadcastKey:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeyBroadcastKey,pData, KEY_MAX_LENGTH);

#else
          iret = DS_nvmWrite(ENpbyBroadcastKey,pData, KEY_MAX_LENGTH);
#endif
          break;
        case ENpbyNVMKey:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeyNVMKey,pData, KEY_MAX_LENGTH);

#else
          iret = DS_nvmWrite(ENpbyNVMKey,pData, KEY_MAX_LENGTH);
#endif
          break;
        case ENpbyNVMKeyEN:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeyNVMKeyEN,pData, KEY_MAX_LENGTH);

#else
          iret = DS_nvmWrite(ENpbyNVMKeyEN,pData, KEY_MAX_LENGTH);
#endif
          break;
        case ENpbyDefaultKey1:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeyDefaultKey1,pData, KEY_MAX_LENGTH);

#else
          iret = DS_nvmWrite(ENpbyDefaultKey1,pData, KEY_MAX_LENGTH);
#endif
          break;
        case ENpbyDefaultKey2:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeypbyDefaultKey2,pData, KEY_MAX_LENGTH);

#else
          iret = DS_nvmWrite(ENpbyDefaultKey2,pData, KEY_MAX_LENGTH);
#endif
          break;
        case ENpbyCodeABKey:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeyCodeABKey,pData, KEY_MAX_LENGTH);

#else
          iret = DS_nvmWrite(ENpbyCodeABKey,pData, KEY_MAX_LENGTH);
#endif
          break;

        case ItselfRollingCode:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeyItselfRollingCode,pData, ROLLING_CODE_LENGTH);
#else
          iret = DS_nvmWrite(ItselfRollingCode,pData, ROLLING_CODE_LENGTH);
#endif
          break;
        case EndDeviceRecvRollingCode:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeyEndDeviceRecvRollingCode,pData, ROLLING_CODE_LENGTH);
#else
          iret = DS_nvmWrite(EndDeviceRecvRollingCode,pData, ROLLING_CODE_LENGTH);
#endif
          break;

        case ENpbyRfmId:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeyRfmId,pData, 1);

#else
          iret = DS_nvmWrite(ENpbyRfmId,pData, 1);
#endif
          break;
        case RfTxPower:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeyRfTxPower,pData, RF_TX_POWER_LENGTH);

#else
          iret = DS_nvmWrite(RfTxPower,pData, RF_TX_POWER_LENGTH);
#endif
          break;
        case RfCtune:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeyRfCtune,pData, RF_CTUNE_LENGTH);
#else
          iret = DS_nvmWrite(RfCtune,pData, RF_CTUNE_LENGTH);
#endif
          break;
        case lfxoCtune:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeylfxoCtune,pData, LFXO_CTUNE_LENGTH);

#else
          iret = DS_nvmWrite(lfxoCtune,pData, LFXO_CTUNE_LENGTH);
#endif
          break;
        case ENpbyPanId:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeyPanId,pData, PANID_LENGTH);

#else
          iret = DS_nvmWrite(ENpbyPanId,pData, PANID_LENGTH);
#endif
        break;

        case ENpbyOption:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeyOption,pData, OPTION_LENGTH);

#else
          iret = DS_nvmWrite(ENpbyOption,pData, OPTION_LENGTH);
#endif
          break;

        case smartPlugCalibration:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeySmartPlugCalibration, pData,SMART_PLUG_CALIBRATION_LENGTH);

#else
          iret = DS_nvmWrite(smartPlugCalibration, pData,SMART_PLUG_CALIBRATION_LENGTH);
#endif
          break;
        case smartPlugEnergy:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(EnbyKeySmartPlugEnergy, pData,SMART_PLUG_ENERGY_LENGTH);

#else
          iret = DS_nvmWrite(smartPlugEnergy, pData,SMART_PLUG_ENERGY_LENGTH);
#endif
          break;
        case smartPlugTimes:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeySmartPlugTimes, pData,SMART_PLUG_TIMES_LENGTH);

#else
          iret = DS_nvmWrite(smartPlugTimes, pData,SMART_PLUG_TIMES_LENGTH);
#endif
          break;
        case onoffState:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeyOnoffState, pData,ONOFF_STATE_LENGTH);

#else
          iret = DS_nvmWrite(onoffState, pData,ONOFF_STATE_LENGTH);
#endif
          break;
        case childLock:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmWrite(ENbyKeyChildLock, pData,CHILD_LOCK_LENGTH);

#else
          iret = DS_nvmWrite(childLock, pData,CHILD_LOCK_LENGTH);
#endif
          break;

#ifdef  HUB_DEVICE
        case ENbyRssiLimit:
          memcpy((char *)&ram_attr.rssi_limit, pData, 1);
          break;
#endif
#ifdef CONFIG_NVM_VERSION
        case ENbyNVMVersion:
          iret = DS_nvmWrite(ENbyKeyNVMVersion, pData,NVMVersion_LENGTH);
          break;
#endif
#ifdef CONFIG_NVM_VERSION
        case ENbyASeqLed:
          iret = DS_nvmWrite(ENbyKeyASeqLed, pData,1);
          break;
#endif
#ifdef CONFIG_NVM_VERSION
        case ENbyASeqOperate:
          iret = DS_nvmWrite(ENbyKeyASeqOperate, pData,1);
          break;
#endif
        default:
          iret = -1;
          break;
    }
    return iret;
}

int getThisParam(DEVICE_ATTRIBUTE_EN attr, void* pData)
{
    if(!pData){
      return -1;
    }
    int iret = 0;
    switch(attr){
#ifdef HUB_DEVICE
        case ENbyEvtA0TNS:
          memcpy(pData, (char *)&ram_attr.evt_a0_tns, 1);
          break;
        case ENbyEvtA1TNS:
          memcpy(pData, (char *)&ram_attr.evt_a1_tns, 1);
          break;
        case ENbyEvtA2TNS:
          memcpy(pData, (char *)&ram_attr.evt_a2_tns, 1);
          break;
        case ENbyEvtA0AckFlag:
          memcpy(pData, (char *)&ram_attr.evt_a0_flag, 1);
          break;
        case ENbyEvtA1AckFlag:
          memcpy(pData, (char *)&ram_attr.evt_a1_flag, 1);
          break;
        case ENbyEvtA2AckFlag:
          memcpy(pData, (char *)&ram_attr.evt_a2_flag, 1);
          break;
        case ENbyHubUsartSeq:
          memcpy(pData, (char *)&ram_attr.hub_usart_seq, 1);
          break;
        case ENbyPanelUsartSeq:
          memcpy(pData, (char *)&ram_attr.panel_usart_seq, 1);
          break;
        case ENbyBcastBusy:
          memcpy(pData, (char *)&ram_attr.bcast_busy, 1);
          break;
        case ENbyCfgReq:
          memcpy(pData, (char *)&ram_attr.cfg_req, 1);
          break;


        case ENbyFreq:
          memcpy(pData, (char *)&ram_attr.freq, 1);
          break;
        case ENbyjamming:
          memcpy(pData, (char *)&ram_attr.jamming, 1);
          break;
        case ENbycustcode:
          memcpy(pData, (char *)&ram_attr.custcode, 1);
          break;
        case ENbyLocalRegister:
          memcpy(pData, (char *)&ram_attr.register_ctrl, 1);
          break;
        case ENbyRegisterMAC:
          memcpy(pData, (char *)&ram_attr.register_mac, MAC_ADDRESS_LENGTH);
          break;
        case ENbyRegisterQrKey:
          memcpy(pData, (char *)&ram_attr.register_qr, 16);
          break;
        case ENbyRegisterSN:
          memcpy(pData, (char *)&ram_attr.register_sn, SN_LENGTH);
          break;
        case ENbyResetMode:
          memcpy(pData, (char *)&ram_attr.reset_mode, 1);
          break;
        case ENbyEnableRetrans:
          memcpy(pData, (char *)&ram_attr.enable_retrans, 1);
          break;
        case ENbyRealRssi:
          memcpy(pData, (char *)&ram_attr.real_rssi, 1);
          break;
        case ENbyAvgRssi:
          memcpy(pData, (char *)&ram_attr.avg_rssi, 1);
          break;
        case ENbyPanelSetOtaMode:
          memcpy(pData, (char *)&ram_attr.ota_panelsetmode, 1);
          break;
        case ENbyPanelSetOtaNum:
          memcpy(pData, (char *)&ram_attr.ota_panelsetnum, 1);
          break;
        case ENbyPanelSetOtaId:
          memcpy(pData, (char *)&ram_attr.ota_panelsetid,OTA_ID_BUF_MAX);
          break;
        case ENbyDelayTxTask:
          memcpy(pData, (char *)&ram_attr.delay_txtask, 1);
          break;
        case ENbyNodeJoinInfo:
          ram_attr.node_join_info_src = DEVICE_SOURCE_NVM;
          if(ram_attr.node_join_info_src == DEVICE_SOURCE_NVM){
#ifdef CONFIG_NVM_VERSION
              iret = DS_nvmRead(ENbyKeyNodeJoinInfo,pData, NODE_JOIN_INFO_LENGTH);

#else
              iret = DS_nvmRead(ENbyNodeJoinInfo,pData, NODE_JOIN_INFO_LENGTH);
#endif
              if(iret != 0){
                  memset(ram_attr.node_join_info,0,NODE_JOIN_INFO_LENGTH);
              }
              else{
                  memcpy(ram_attr.node_join_info,pData,NODE_JOIN_INFO_LENGTH);
              }
//              ram_attr.node_join_info_src = DEVICE_SOURCE_RAM;
          }
          else{
//              ram_attr.node_join_info_src = DEVICE_SOURCE_NVM;
              memcpy(pData,ram_attr.node_join_info,NODE_JOIN_INFO_LENGTH);
          }
          break;
#else
        case ENbyQrfH1:
          memcpy(pData,&rfm_ram.qrfH1,1);
          break;
        case ENbyQrfH2:
          memcpy(pData,&rfm_ram.qrfH2,1);
          break;
        case ENbyQrfR1:
          memcpy(pData,&rfm_ram.qrfR1,1);
          break;
        case ENbyQrfR2:
          memcpy(pData,&rfm_ram.qrfR2,1);
          break;
#endif
          /* hard info*/
        case ENpbyKeyM://sn
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeySN,pData, SN_LENGTH);
#else
          iret = DS_nvmRead(ENpbyKeyM,pData, SN_LENGTH);
#endif
          break;
        case ENbyHardType:
          if(SYSTEM_GetFlashSize()>256) {
              ((uint8_t *)pData)[0] = HARD_TYPE_SILICON_LAB_512;
          }
          else {
              ((uint8_t *)pData)[0] = HARD_TYPE_SILICON_LAB_256;
          }
          iret = 0;
          break;
        case ENbyModelType:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeyModelType,pData, 1);

#else
          iret = DS_nvmRead(ENbyModelType,pData, 1);
#endif
          break;
        case ENpbyRfVer:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeyRfVer,pData, PRF_LENGTH);

#else
          iret = DS_nvmRead(ENpbyRfVer,pData, PRF_LENGTH);
#endif
          break;
        case ENpbySensorVer:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeySensorVer,pData, 3);
#else
          iret = DS_nvmRead(ENpbySensorVer,pData, 3);
#endif
          break;
        case ENbyDeviceType:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeyDeviceType,pData, 1);

#else
          iret = DS_nvmRead(ENbyDeviceType,pData, 1);
#endif
          break;
        case ENpbyMacID:
        //TODO:测试数据,正式mac address改为工厂烧录
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeyMacID,pData, MAC_ADDRESS_LENGTH);

#else
          iret = DS_nvmRead(ENpbyMacID,pData, MAC_ADDRESS_LENGTH);
#endif
          break;
        case ENbyTransFileType:
          memcpy(pData, (char *)&file_ram.file_type, 1);
          break;
        case ENbyOtaUpdatemeID:
          memcpy(pData, (char *)&file_ram.updateme_id, OTA_ID_BUF_MAX);
          break;
        case ENbyOtaUpdatemeIDNum:
          memcpy(pData, (char *)&file_ram.updateme_id_num, 1);
          break;
        //case ENbyHandShakeCount:
        //  memcpy(pData, (char *)&file_ram.handshake_count, 1);
        //  break;
        case ENbyOtaRequestFlag:
          memcpy(pData, (char *)&file_ram.request_flag, 1);
          break;
        case ENbyOtaRequestKeyValue:
          memcpy(pData, (char *)&file_ram.request_value, OTA_REQUEST_VALUE_LENGTH);
          break;
        case ENbyOtaConfirmFlag:
          memcpy(pData, (char *)&file_ram.confirm_flag, 1);
          break;
        case ENbyOtaConfirmKeyValue:
          memcpy(pData, (char *)&file_ram.confirm_value, OTA_CONFIRM_VALUE_LENGTH);
          break;
        case ENbyOtaConSultKeyValue:
          memcpy(pData, (char *)&file_ram.consult_value, OTA_CONSULT_KEYVALUE_LENGTH);
          break;
        case ENbyReadFileLinkIdx:
          memcpy(pData, (char *)&file_ram.read_link_idx, 1);
          break;
        case ENbyWriteFileLinkIdx:
          memcpy(pData, (char *)&file_ram.write_link_idx, 1);
          break;
        case ENpbySystemID:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeySystemID,pData, 3);

#else
          iret = DS_nvmRead(ENpbySystemID,pData, 3);
#endif
//产测模式hub使用 TEST_SYSTEMID   0xFFFFFF
#if defined(HUB_AS_TEST_MACHINE) && defined (HUB_DEVICE) 
          uint8_t buf[3] = {0xFF,0xFF,0xFF};
          memcpy(pData,buf,3);
#endif
          break;

        case ENpbyKeyA:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeyKeyA,pData, KEY_MAX_LENGTH);

#else
          iret = DS_nvmRead(ENpbyKeyA,pData, KEY_MAX_LENGTH);
#endif
        break;
        case ENpbyKeyB:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeyKeyB,pData, KEY_MAX_LENGTH);

#else
          iret = DS_nvmRead(ENpbyKeyB,pData, KEY_MAX_LENGTH);
#endif
          break;
        case ENpbySystemKey:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeySystemKey,pData, KEY_MAX_LENGTH);

#else
          iret = DS_nvmRead(ENpbySystemKey,pData, KEY_MAX_LENGTH);
#endif
          break;
        case ENpbyBroadcastKey:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeyBroadcastKey,pData, KEY_MAX_LENGTH);

#else
          iret = DS_nvmRead(ENpbyBroadcastKey,pData, KEY_MAX_LENGTH);
#endif
          break;
        case ENpbyNVMKey:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeyNVMKey,pData, KEY_MAX_LENGTH);

#else
          iret = DS_nvmRead(ENpbyNVMKey,pData, KEY_MAX_LENGTH);
#endif
          break;
        case ENpbyNVMKeyEN:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeyNVMKeyEN,pData, KEY_MAX_LENGTH);

#else
          iret = DS_nvmRead(ENpbyNVMKeyEN,pData, KEY_MAX_LENGTH);
#endif
          break;
        case ENpbyDefaultKey1:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeyDefaultKey1,pData, KEY_MAX_LENGTH);

#else
          iret = DS_nvmRead(ENpbyDefaultKey1,pData, KEY_MAX_LENGTH);
#endif
          break;
        case ENpbyDefaultKey2:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeypbyDefaultKey2,pData, KEY_MAX_LENGTH);

#else
          iret = DS_nvmRead(ENpbyDefaultKey2,pData, KEY_MAX_LENGTH);
#endif
          break;
        case ENpbyCodeABKey:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeyCodeABKey,pData, KEY_MAX_LENGTH);

#else
          iret = DS_nvmRead(ENpbyCodeABKey,pData, KEY_MAX_LENGTH);
#endif
          break;

        case ItselfRollingCode:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeyItselfRollingCode,pData, ROLLING_CODE_LENGTH);

#else
          iret = DS_nvmRead(ItselfRollingCode,pData, ROLLING_CODE_LENGTH);
#endif
          break;
        case EndDeviceRecvRollingCode:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeyEndDeviceRecvRollingCode,pData, ROLLING_CODE_LENGTH);
#else
          iret = DS_nvmRead(EndDeviceRecvRollingCode,pData, ROLLING_CODE_LENGTH);
#endif
          break;

        case ENpbyRfmId:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeyRfmId,pData, 1);

#else
          iret = DS_nvmRead(ENpbyRfmId,pData, 1);
#endif
          break;
        case RfTxPower:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeyRfTxPower,pData, RF_TX_POWER_LENGTH);

#else
          iret = DS_nvmRead(RfTxPower,pData, RF_TX_POWER_LENGTH);
#endif
          break;
        case RfCtune:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeyRfCtune,pData, RF_CTUNE_LENGTH);

#else
          iret = DS_nvmRead(RfCtune,pData, RF_CTUNE_LENGTH);
#endif
          break;
        case lfxoCtune:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeylfxoCtune,pData, LFXO_CTUNE_LENGTH);

#else
          iret = DS_nvmRead(lfxoCtune,pData, LFXO_CTUNE_LENGTH);
#endif
          break;
        case ENpbyPanId:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeyPanId,pData, PANID_LENGTH);

#else
          iret = DS_nvmRead(ENpbyPanId,pData, PANID_LENGTH);
#endif
        break;

        case ENpbyOption:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeyOption,pData, OPTION_LENGTH);

#else
          iret = DS_nvmRead(ENpbyOption,pData, OPTION_LENGTH);
#endif
          break;

        case smartPlugCalibration:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeySmartPlugCalibration, pData,SMART_PLUG_CALIBRATION_LENGTH);

#else
          iret = DS_nvmRead(smartPlugCalibration, pData,SMART_PLUG_CALIBRATION_LENGTH);
#endif
          break;
        case onoffState:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeyOnoffState, pData,ONOFF_STATE_LENGTH);

#else
          iret = DS_nvmRead(onoffState, pData,ONOFF_STATE_LENGTH);
#endif
          break;
        case childLock:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeyChildLock, pData,CHILD_LOCK_LENGTH);

#else
          iret = DS_nvmRead(childLock, pData,CHILD_LOCK_LENGTH);
#endif
          break;
        case smartPlugEnergy:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(EnbyKeySmartPlugEnergy, pData,SMART_PLUG_ENERGY_LENGTH);

#else
          iret = DS_nvmRead(smartPlugEnergy, pData,SMART_PLUG_ENERGY_LENGTH);
#endif
          break;
        case smartPlugTimes:
#ifdef CONFIG_NVM_VERSION
          iret = DS_nvmRead(ENbyKeySmartPlugTimes, pData,SMART_PLUG_TIMES_LENGTH);

#else
          iret = DS_nvmRead(smartPlugTimes, pData,SMART_PLUG_TIMES_LENGTH);
#endif
          break;
#ifdef  HUB_DEVICE
        case ENbyRssiLimit:
          memcpy(pData,(char *)&ram_attr.rssi_limit, 1);
          break;
#endif
#ifdef CONFIG_NVM_VERSION
        case ENbyNVMVersion:
          iret = DS_nvmRead(ENbyKeyNVMVersion, pData,NVMVersion_LENGTH);
          break;
#endif
#ifdef CONFIG_NVM_VERSION
        case ENbyASeqLed:
          iret = DS_nvmRead(ENbyKeyASeqLed, pData,1);
          break;
#endif
#ifdef CONFIG_NVM_VERSION
        case ENbyASeqOperate:
          iret = DS_nvmRead(ENbyKeyASeqOperate, pData,1);
          break;
#endif
        default:
          iret = -1;
          break;
    }
    return iret;
}


int setDeviceParam(uint8_t nodeId ,DEVICE_ATTRIBUTE_EN attr, void* pData)
{
  int iret = 0;
  if(nodeId == 0|| nodeId == 0xff){
     return -1;
  }
  if(!pData){
     return -1;
  }
  switch(attr){
#ifdef HUB_DEVICE
      case ENbyLedCtrlFlag:
        memcpy((char *)&ram_attr.led_ctrl_flag[nodeId], pData, 1);
        break;
      case ENbyOperateCtrlFlag:
        memcpy((char *)&ram_attr.operate_ctrl_flag[nodeId], pData, 1);
        break;
      case ENbyKeyValueGetFlag:
        //memcpy((char *)&ram_attr.keyvalue_get_flag[nodeId], pData, 1);
        break;
      case ENbyOtaConSultFlag:
        memcpy((char *)&ram_attr.ota_consult_flag[nodeId], pData, 1);
        break;
      case ENbyLedCtrl:
        memcpy((char *)&ram_attr.led_ctrl[nodeId], pData, LEDCTRL_LENGTH);
        break;
      case ENbyOperateCtrl:
        memcpy((char *)&ram_attr.operate_ctrl[nodeId], pData, OPERATECTRL_LENGTH);
        break;
      case ENbyKeyValueGet:
        //memcpy((char *)&ram_attr.keyvalue_get[nodeId], pData, GETKEYVALUE_LENGTH);
        break;
      case ENbyIOenLock:
        if(nodeId >= RFMID_EN_INDEX_IO_FIRST && nodeId <= RFMID_EN_INDEX_IO_LAST){
            memcpy((char *)&ram_attr.IOen_lock[nodeId - 1], pData, 1); //nodeId 1- 128
        }
        break;
#endif
      case ENpbyNodeSNFirst:
#ifdef CONFIG_NVM_VERSION
        iret = DS_nvmWriteOfsWithPackLen(ENbyKeyNodeRegInfoFirst+nodeId-1,pData, NODEREGINFO_SN_LEN,NODEREGINFO_SN_OFS,NODEREGINFO_MAX_LEN);

#else
        iret = DS_nvmWrite((ENpbyNodeSNFirst + nodeId),pData, SN_LENGTH);
#endif
        break;
      case ENpbyNodeQrfH1First:
#ifdef HUB_DEVICE
        if(((uint8_t *)pData)[0] != ram_attr.qrfh1_buf[nodeId]){
            ram_attr.qrfh1_buf[nodeId] = ((uint8_t *)pData)[0];
#ifdef CONFIG_NVM_VERSION

            iret = DS_nvmWriteOfsWithPackLen(ENbyKeyNodeQrfH12GroupFirst+nodeId-1,pData, NodeQrfH12Group_QrfH1_LEN,NodeQrfH12Group_QrfH1_OFS,NodeQrfH12Group_MAX_LEN);

#else
            iret = DS_nvmWrite((ENpbyNodeQrfH1First + nodeId), pData, 1);
#endif
        }
        if(nodeId >= RFMID_EN_INDEX_IO_FIRST && nodeId <= RFMID_EN_INDEX_IO_LAST){
            ram_attr.IOen_lock[nodeId - 1] = 0;
        }
#endif
        break;
      case ENpbyNodeQrfH2First:
#ifdef HUB_DEVICE
        //只改RAM，不存NVM
        memcpy((char *)&ram_attr.qrfh2_buf[nodeId], pData, 1);
        if(ram_attr.qrfh2_buf[nodeId] == 0){
            set_qrfh_countdown(nodeId, 0);
        }else{
            set_qrfh_countdown(nodeId, QRFH2_COUNTDOWN);
        }
#endif
        break;
      case ENpbyNodeQrfR1First:
#ifdef HUB_DEVICE
        memcpy((char *)&ram_attr.qrfr1_buf[nodeId], pData, 1);
#endif
        break;
      case ENpbyNodeQrfR2First:
#ifdef HUB_DEVICE
        memcpy((char *)&ram_attr.qrfr2_buf[nodeId], pData, 1);
#endif
        break;
      case ENpbyNodeGroupIdxFirst:
#ifdef CONFIG_NVM_VERSION
        iret = DS_nvmWrite((ENbyKeyNodeGroupIdxFirst + nodeId-1),pData, NodeGroupIdx_LEN);

#else
        iret = DS_nvmWrite((ENpbyNodeGroupIdxFirst + nodeId),pData, 1);
#endif
        break;
      case ENpbyNodeOptionFirst:
#ifdef HUB_DEVICE
        if(memcmp(ram_attr.opption_buf[nodeId], (uint8_t *)pData, OPTION_LENGTH)){
            memcpy(ram_attr.opption_buf[nodeId], (uint8_t *)pData, OPTION_LENGTH);

#ifdef CONFIG_NVM_VERSION
            iret = DS_nvmWrite((ENbyKeyNodeOptionFirst + nodeId-1),pData, OPTION_LENGTH);
#else
            iret = DS_nvmWrite((ENpbyNodeOptionFirst + nodeId),pData, OPTION_LENGTH);
#endif
        }
#endif
        break;
      case ENpbyNodeDeviceTypeFirst:
#ifdef CONFIG_NVM_VERSION
        iret = DS_nvmWriteOfsWithPackLen(ENbyKeyNodeRegInfoFirst+nodeId-1,pData, NODEREGINFO_TYPE_LEN,NODEREGINFO_TYPE_OFS,NODEREGINFO_MAX_LEN);
#else
        iret = DS_nvmWrite((ENpbyNodeDeviceTypeFirst + nodeId),pData, 3);
#endif
        break;
      case ENbyNodeDeviceOptionFirst:
#ifdef CONFIG_NVM_VERSION
        iret = DS_nvmWriteOfsWithPackLen(ENbyKeyNodeRegInfoFirst+nodeId-1,pData, NODEREGINFO_OPTION_LEN,NODEREGINFO_OPTION_OPS,NODEREGINFO_MAX_LEN);
#else
        DS_app_log_error("Node device option not support\n");
#endif

        break;
#if HUB_DEVICE
      case HubRecvRollingCodeFirst:
#ifdef CONFIG_NVM_VERSION
        iret = DS_nvmWrite((ENbyKeyHubRecvRollingCodeFirst + nodeId-1),pData, ROLLING_CODE_LENGTH);
#else
        iret = DS_nvmWrite((HubRecvRollingCodeFirst + nodeId),pData, ROLLING_CODE_LENGTH);
#endif
        break;
#endif
      default:
        iret = -1;
        break;
  }
  return iret;
}

int getDeviceParam(uint8_t nodeId ,DEVICE_ATTRIBUTE_EN attr, void* pData)
{
  int iret = 0;
  if(nodeId == 0|| nodeId == 0xff){
     return -1;
  }
  if(!pData){
     return -1;
  }
  switch(attr){
#ifdef HUB_DEVICE
      case ENbyLedCtrlFlag:
        memcpy(pData, (char *)&ram_attr.led_ctrl_flag[nodeId], 1);
        break;
      case ENbyOperateCtrlFlag:
        memcpy(pData, (char *)&ram_attr.operate_ctrl_flag[nodeId], 1);
        break;
      case ENbyKeyValueGetFlag:
        //memcpy(pData, (char *)&ram_attr.keyvalue_get_flag[nodeId], 1);
        ((char *)pData)[0] = 0;
        break;
      case ENbyOtaConSultFlag:
        memcpy(pData, (char *)&ram_attr.ota_consult_flag[nodeId], 1);
        break;
      case ENbyLedCtrl:
        memcpy(pData, (char *)&ram_attr.led_ctrl[nodeId], LEDCTRL_LENGTH);
        break;
      case ENbyOperateCtrl:
        memcpy(pData, (char *)&ram_attr.operate_ctrl[nodeId], OPERATECTRL_LENGTH);
        break;
      case ENbyKeyValueGet:
        //memcpy(pData, (char *)&ram_attr.keyvalue_get[nodeId], GETKEYVALUE_LENGTH);
        ((char *)pData)[0] = 0;
        break;
      case ENbyIOenLock:
        if(nodeId >= RFMID_EN_INDEX_IO_FIRST && nodeId <= RFMID_EN_INDEX_IO_LAST){
            memcpy(pData, (char *)&ram_attr.IOen_lock[nodeId - 1], 1);//nodeId 1- 128
        }else{
            ((char *)pData)[0] = 0;
        }
        break;
#endif
      case ENpbyNodeSNFirst:
#ifdef CONFIG_NVM_VERSION
        iret = DS_nvmReadOfs(ENbyKeyNodeRegInfoFirst+nodeId-1,pData, NODEREGINFO_SN_LEN,NODEREGINFO_SN_OFS);
#else
        iret = DS_nvmRead((ENpbyNodeSNFirst + nodeId),pData, SN_LENGTH);
#endif
        break;
      case ENpbyNodeQrfH1First:
#ifdef HUB_DEVICE
        memcpy(pData, (char *)&ram_attr.qrfh1_buf[nodeId], 1);
        if(nodeId >= RFMID_EN_INDEX_IO_FIRST && nodeId <= RFMID_EN_INDEX_IO_LAST){
            if(ram_attr.IOen_lock[nodeId - 1]){
                ((char *)pData)[0] |= (0x1 << 7);  //IOEN 强制置1
            }
        }
#endif
        break;
      case ENpbyNodeQrfH2First:
#ifdef HUB_DEVICE
        memcpy(pData, (char *)&ram_attr.qrfh2_buf[nodeId], 1);
#endif
        break;
      case ENpbyNodeQrfR1First:
#ifdef HUB_DEVICE
        memcpy(pData, (char *)&ram_attr.qrfr1_buf[nodeId], 1);
#endif
        break;
      case ENpbyNodeQrfR2First:
#ifdef HUB_DEVICE
        memcpy(pData, (char *)&ram_attr.qrfr2_buf[nodeId], 1);
#endif
        break;
      case ENpbyNodeGroupIdxFirst:
#ifdef CONFIG_NVM_VERSION
        iret = DS_nvmRead((ENbyKeyNodeGroupIdxFirst + nodeId-1),pData, NodeGroupIdx_LEN);
#else
        iret = DS_nvmRead((ENpbyNodeGroupIdxFirst + nodeId),pData, 1);
#endif
        break;
      case ENpbyNodeOptionFirst:
#ifdef HUB_DEVICE
        memcpy(pData, ram_attr.opption_buf[nodeId], OPTION_LENGTH);
#endif
        break;
      case ENpbyNodeDeviceTypeFirst:
#ifdef CONFIG_NVM_VERSION
        iret = DS_nvmReadOfs(ENbyKeyNodeRegInfoFirst+nodeId-1,pData, NODEREGINFO_TYPE_LEN,NODEREGINFO_TYPE_OFS);
#else
        iret = DS_nvmRead((ENpbyNodeDeviceTypeFirst + nodeId),pData, 3);
#endif
        break;
      case ENbyNodeDeviceOptionFirst:
#ifdef CONFIG_NVM_VERSION
        iret = DS_nvmReadOfs(ENbyKeyNodeRegInfoFirst+nodeId-1,pData, NODEREGINFO_OPTION_LEN,NODEREGINFO_OPTION_OPS);
#else
        DS_app_log_error("Node device option not support\n");
#endif

        break;
#if HUB_DEVICE
      case HubRecvRollingCodeFirst:
#ifdef CONFIG_NVM_VERSION
        iret = DS_nvmRead((ENbyKeyHubRecvRollingCodeFirst + nodeId-1),pData, ROLLING_CODE_LENGTH);
#else
        iret = DS_nvmRead((HubRecvRollingCodeFirst + nodeId),pData, ROLLING_CODE_LENGTH);
#endif
        break;
#endif
      default:
        iret = -1;
        break;
  }
  return iret;
}


#if defined (HUB_DEVICE)
//ram_attr.mac 与 flash里的rfm mac应该始终保持一致
bool isJoinMac(uint8_t *mac)
{
  uint8_t id=0;
  if(get_net_printf_log() == true){
      DS_app_log_error("MAC: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\r\n",
                   mac[0],mac[1],
                   mac[2],mac[3],
                   mac[4],mac[5],
                   mac[6],mac[7]
                   );
  }
  for(id=1;id<NODE_MAX_COUNT;id++){
      if(memcmp(ram_attr.mac[id-1],mac,MAC_ADDRESS_LENGTH) == 0){
          DS_app_log_error("ID[%d]mac same\n",id);
          return true;
      }
  }
  if(get_net_printf_log() == true){
      DS_app_log_error("Null ID mac same\r\n");
  }
  return false;
}
void printAllNodeJoinMac (void)
{
  uint8_t id=0;
  DS_app_log_error("Reg info mac:\n");
  for(id=1;id<NODE_MAX_COUNT;id++){

      DS_app_log_error("[%d] %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
                       id,
                       ram_attr.mac[id-1][0],ram_attr.mac[id-1][1],
                       ram_attr.mac[id-1][2],ram_attr.mac[id-1][3],
                       ram_attr.mac[id-1][4],ram_attr.mac[id-1][5],
                       ram_attr.mac[id-1][6],ram_attr.mac[id-1][7]
                       );
  }
}
void printOneNodeJoinMac(uint8_t id)
{
  DS_app_log_error("Reg info mac:\n");
  DS_app_log_error("[%d] %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
                   id,
                   ram_attr.mac[id-1][0],ram_attr.mac[id-1][1],
                   ram_attr.mac[id-1][2],ram_attr.mac[id-1][3],
                   ram_attr.mac[id-1][4],ram_attr.mac[id-1][5],
                   ram_attr.mac[id-1][6],ram_attr.mac[id-1][7]
                   );
}
/**********************************************
 * @brief 获取所有节点的mac到RAM中(有效的MAC,不含C1)
 *
 *
 * @note 该函数有一定的延时,建议在上电时候使用
 *
 */
void getAllNodeJoinMac (void)
{
  uint8_t x,y,id=0;
  uint8_t buf[NODE_JOIN_INFO_LENGTH]={0};
  uint8_t mac[MAC_ADDRESS_LENGTH]={0};
  uint8_t i=0,ret=0,option=0;

  if(getThisParam(ENbyNodeJoinInfo,buf) != 0){
      for(i=1;i<NODE_MAX_COUNT;i++){
          //出厂设置为全0
          memset(ram_attr.mac[i-1],0,MAC_ADDRESS_LENGTH);
      }
  }
  else {
      for(i=1;i<NODE_MAX_COUNT;i++){
          //出厂设置为全0
          memset(ram_attr.mac[i-1],0,MAC_ADDRESS_LENGTH);
      }
      //查找ID,copy mac
      for(x=0;x<NODE_JOIN_INFO_LENGTH;x++){
          for(y=0;y<8;y++){
            if( reg_getInfoId(buf,x,y,&id) == true){
                //TODO:check option
                ret = getDeviceParam(id,ENbyNodeDeviceOptionFirst,&option);
                if(option == ENbyNodeRegInfoOption_C3 && ret ==0){
                    getNodeJoinMac(mac,id);
                    memcpy(&ram_attr.mac[id-1][0],&mac[0],MAC_ADDRESS_LENGTH);
                }
            }
          }
      }
  }
}
void getNodeJoinMac (uint8_t *mac,uint8_t id)
{
  int iret = 0;
  ram_attr.mac_src = DEVICE_SOURCE_NVM;
  if(ram_attr.mac_src == DEVICE_SOURCE_NVM){
//      ram_attr.mac_src = DEVICE_SOURCE_RAM;
#ifdef CONFIG_NVM_VERSION
      iret = DS_nvmReadOfs(ENbyKeyNodeRegInfoFirst+id-1,mac, NODEREGINFO_MAC_LEN,NODEREGINFO_MAC_OFS);

#else
      iret = DS_nvmRead(ENbyNodeMacAddrFirst+id-1,mac, MAC_ADDRESS_LENGTH);
#endif
      if(iret != 0){
          memset(ram_attr.mac[id-1],0,MAC_ADDRESS_LENGTH);
      }
      else{
          memcpy(ram_attr.mac[id-1],mac,MAC_ADDRESS_LENGTH);
      }
  }
  else {
      memcpy(mac,ram_attr.mac[id-1],MAC_ADDRESS_LENGTH);
  }
}
void setNodeJoinMac(uint8_t *mac,uint8_t id)
{
#ifdef CONFIG_NVM_VERSION
  DS_nvmWriteOfsWithPackLen(ENbyKeyNodeRegInfoFirst+id-1,mac, NODEREGINFO_MAC_LEN,NODEREGINFO_MAC_OFS,NODEREGINFO_MAX_LEN);
#else
  DS_nvmWrite(ENbyNodeMacAddrFirst+id-1,mac, MAC_ADDRESS_LENGTH);
#endif
  memcpy(ram_attr.mac[id-1],mac,MAC_ADDRESS_LENGTH);
}
void getNodeJoinCodeAB(uint8_t *key,uint8_t id)
{
#ifdef CONFIG_NVM_VERSION
  DS_nvmReadOfs(ENbyKeyNodeRegInfoFirst+id-1,key, NODEREGINFO_CODEAB_LEN,NODEREGINFO_CODEAB_OFS);
#else
  DS_nvmRead(ENpbyCodeABNodeLast+id-1,key, KEY_MAX_LENGTH);
#endif
}
void setNodeJoinCodeAB(uint8_t *key,uint8_t id)
{
#ifdef CONFIG_NVM_VERSION
  DS_nvmWriteOfsWithPackLen(ENbyKeyNodeRegInfoFirst+id-1,key, NODEREGINFO_CODEAB_LEN,NODEREGINFO_CODEAB_OFS,NODEREGINFO_MAX_LEN);
#else
  DS_nvmWrite(ENpbyCodeABNodeLast+id-1,key, KEY_MAX_LENGTH);
#endif
}
#endif
uint32_t getMacAdd4(void)
{
  uint8_t buff[8];

  getThisParam(ENpbyMacID,buff);
  return l_get_be64(buff)&0xFFFFFFFF;
}
/*
 *
 */

#if defined (HUB_DEVICE)
void set_node_join_info_src_nvm(void)
{

  ram_attr.node_join_info_src = DEVICE_SOURCE_NVM;
  uint8_t buf[3]={0};

  if(getThisParam(ENpbySystemID,buf) != 0){
      /*
       * systemID生成规则
       */
      buf[0] = (getMacAdd4()>>16)&0xFF;
      buf[1] = (getMacAdd4()>>8)&0xFF;
      buf[2] = getMacAdd4()&0xFF;
      setThisParam(ENpbySystemID,buf);
  }
  DS_app_log_error("system ID init:0x%02x%02x%02x\n",buf[0],buf[1],buf[2]);
  if(getThisParam(ENpbyPanId,buf) != 0){
      buf[0] = (getMacAdd4()>>16)&0xFF;
      buf[1] = (getMacAdd4()>>8)&0xFF;
      buf[2] = getMacAdd4()&0xFF;
      setThisParam(ENpbyPanId,buf);
  }
  DS_app_log_error("panID init:    0x%02x%02x%02x\n",buf[0],buf[1],buf[2]);
}

static void qrfh_opption_init(void)
{
  int iret = 0;
  uint8_t qrfh1 = 0;
  //uint8_t qrfh2 = 0;
  uint8_t opption[OPTION_LENGTH] = {0};

  for(uint8_t i = 1; i < NODE_MAX_COUNT; i++){
#ifdef CONFIG_NVM_VERSION

      iret = DS_nvmReadOfs(ENbyKeyNodeQrfH12GroupFirst+i-1,&qrfh1, NodeQrfH12Group_QrfH1_LEN,NodeQrfH12Group_QrfH1_OFS);
      ram_attr.qrfh1_buf[i] = (iret)?0 : qrfh1;
      //iret = DS_nvmReadOfs(ENbyKeyNodeQrfH12GroupFirst+i-1,&qrfh2, NodeQrfH12Group_QrfH2_LEN,NodeQrfH12Group_QrfH2_OFS);
      //ram_attr.qrfh2_buf[i] = (iret)?0 : qrfh2;
      ram_attr.qrfh2_buf[i] = 0;
      iret = DS_nvmRead((ENbyKeyNodeOptionFirst + i-1), opption, OPTION_LENGTH);

#else
      iret = DS_nvmRead((ENpbyNodeQrfH1First + i), &qrfh1, 1);
      ram_attr.qrfh1_buf[i] = (iret)?0 : qrfh1;
      //iret = DS_nvmRead((ENpbyNodeQrfH2First + i), &qrfh2, 1);
      //ram_attr.qrfh2_buf[i] = (iret)?0 : qrfh2;
      ram_attr.qrfh2_buf[i] = 0;
      iret = DS_nvmRead((ENpbyNodeOptionFirst + i), opption, OPTION_LENGTH);
#endif
      if(iret == 0){
          memcpy(ram_attr.opption_buf[i], opption, OPTION_LENGTH);
      }
  }
}
#endif

#ifdef CONFIG_NVM_VERSION
void nvm_getNVMVersion (void)
{
  uint16_t ver=0;
  uint8_t ret=0;


  ret = getThisParam(ENbyNVMVersion,&ver);
  if(ret != 0){
      ver=CONFIG_NVM_VERSION;
      setThisParam(ENbyNVMVersion,&ver);
      DS_app_log_error("NVM Version: %d\n",ver);
  }
  else{
      if(ver!=CONFIG_NVM_VERSION){
          //TODO:此处后续可以作为NVM Key调整后,进行key值兼容性使用
          DS_app_log_error("NVM Version update: V%d->V%d\n",ver,CONFIG_NVM_VERSION);
          ver=CONFIG_NVM_VERSION;
          setThisParam(ENbyNVMVersion,&ver);
      }
      else{
          DS_app_log_error("NVM Version: %d\n",ver);
      }
  }

}

#endif
/*
 *@brief 关于device参数初始化
 *@note
 */
void nvm_device_init (void)
{
#if defined (RFM_DEVICE)
  uint8_t sn[17] = {0};
  uint32_t sensorVer = 0x00;
#endif
  DS_nvmInit();
  get_hard_information((uint8_t *)&hard_info);
#ifdef CONFIG_NVM_VERSION
  nvm_getNVMVersion();
#endif
#ifdef RBF_DEVICE
  if(get_pandid_test() == true){
      rfm_formatting_no_reset();
  }
#endif
  netKeyInit();
  itself_rolling_code_init(START_UP_INIT,0);
  api_log_enable_init();
#ifdef HUB_DEVICE
    for(uint8_t i = 1; i < NODE_MAX_COUNT; i++){
        recv_rolling_code_init(START_UP_INIT, i, 0);
    }
    qrfh_opption_init();
    getAllNodeJoinMac();
    if(DS_nvmRead(ENbyKeyRfReq, &eRfFreq, 1) != NVM_OK){
        DS_app_log_error("NVM Freq NULL\r\n");
    }
    printfDeviceRfFreqInfo();
#else
    //if(hard_info.sensorVer[0] <= 1 && hard_info.sensorVer[1] < 1){
    sensorVer = hard_info.sensorVer[0] << 16 | hard_info.sensorVer[1] << 8 | hard_info.sensorVer[2];
    if(sensorVer <= 0x010100){  //1.1.0及以内的版本，不具备
        DS_nvmWrite(ENbyKeyRfReq, &eRfFreq, 1);
    }else{
        if(DS_nvmRead(ENbyKeyRfReq, &eRfFreq, 1) != NVM_OK){
            eRfFreq = RF_FREQ_868MHZ; //默认868
            DS_nvmWrite(ENbyKeyRfReq, &eRfFreq, 1);
        }
    }
    recv_rolling_code_init(START_UP_INIT, 0, 0);
#endif
#if defined (RFM_DEVICE)
  DS_app_log_error("\r\n++++++++++Hard info :++++++++++\r\n");
  DS_app_log_error("modelType =%d\r\n",hard_info.modelType);
  DS_app_log_error("deviceType=%d\r\n",hard_info.deviceType);
  DS_app_log_error("hardType=%d\r\n",hard_info.hardType);
  DS_app_log_error("RFver:%02x%02x%02x\r\n",hard_info.pRfVer[0],hard_info.pRfVer[1],hard_info.pRfVer[2]);
  DS_app_log_error("senVer:%02x%02x%02x\r\n",hard_info.sensorVer[0],hard_info.sensorVer[1],hard_info.sensorVer[2]);
  getThisParam(ENpbyKeyM, sn);
  DS_app_log_error("sn:%s\r\n",sn);
  DS_app_log_error("+++++++++++++++++++++++++++++++++++\r\n");
#endif

}


bool memcmp_sn(unsigned char *sn)
{
  unsigned char register_sn[SN_LENGTH + 1] = {'\0'};
  if(!sn){
      return false;
  }
  getThisParam(ENbyRegisterSN, (unsigned char *)register_sn);
  if(register_sn[0] == '\0'){
      return true;
  }
  return ((memcmp(register_sn, sn, SN_LENGTH) == 0)?true:false);
}

int set_api_log_enable(API_LOG_E api_module, bool onoff)
{
  int iret = 0;
  switch(api_module){
    case HUB_API_LOG:
      if(onoff){
          (log_enable[0] |= (1 << 0));
      }else{
          (log_enable[0] &= ~(1 << 0));
      }
      break;
    case FILE_API_LOG:
      if(onoff){
          (log_enable[0] |= (1 << 1));
      }else{
          (log_enable[0] &= ~(1 << 1));
      }
      break;
    case MAC_API_LOG:
      if(onoff){
          (log_enable[0] |= (1 << 2));
      }else{
          (log_enable[0] &= ~(1 << 2));
      }
      break;
    case NET_API_LOG:
      if(onoff){
          (log_enable[0] |= (1 << 3));
      }else{
          (log_enable[0] &= ~(1 << 3));
      }
      break;
    default:
      break;
  }
  iret = DS_nvmWrite(ENbyKeyLogEnable, log_enable, 4);
  return iret;
}

int get_api_log_enable(API_LOG_E api_module, bool *ptr_onoff)
{
  switch(api_module){
    case HUB_API_LOG:
      *ptr_onoff = ((log_enable[0] & (1 << 0)) >> 0);
      break;
    case FILE_API_LOG:
      *ptr_onoff = ((log_enable[0] & (1 << 1)) >> 1);
      break;
    case MAC_API_LOG:
      *ptr_onoff = ((log_enable[0] & (1 << 2)) >> 2);
      break;
    case NET_API_LOG:
      *ptr_onoff = ((log_enable[0] & (1 << 3)) >> 3);
      break;
    default:
      *ptr_onoff = 0;
      break;
  }
  return 0;
}

int set_api_log_enable_multiple_module(unsigned char *byte1,
                                       unsigned char *byte2,
                                       unsigned char *byte3,
                                       unsigned char *byte4)
{
  int iret = 0;
  if(byte1){
      log_enable[0] = byte1[0];
  }
  if(byte2){
      log_enable[1] = byte2[0];
  }
  if(byte3){
      log_enable[2] = byte3[0];
  }
  if(byte4){
      log_enable[3] = byte4[0];
  }
  iret = DS_nvmWrite(ENbyKeyLogEnable, log_enable, 4);
  return iret;
}

int api_log_enable_init(void)
{
  int iret = 0;
  iret = DS_nvmRead(ENbyKeyLogEnable, log_enable, 4);
  if(iret != NVM_OK){
      memset(log_enable, 0, sizeof(log_enable));
  }
  DS_app_log_hexdump_error("[log]",log_enable,4);
  return iret;
}

void clean_device_ram_qrfh(unsigned char rfmid)
{
#ifdef HUB_DEVICE
  if(rfmid == 0 || rfmid == 0xff ){
      return;
  }
  if(rfmid >= RFMID_EN_INDEX_IO_FIRST && rfmid <= RFMID_EN_INDEX_IO_LAST){
      ram_attr.IOen_lock[rfmid - 1] = 0;
  }
  ram_attr.qrfh1_buf[rfmid] = 0;
  ram_attr.qrfh2_buf[rfmid] = 0;
  set_qrfh_countdown(rfmid, 0); //调用了qrfh1_2擦除接口，就不会调 setDeviceParam ENpbyNodeQrfH2First
#else
  (void)rfmid;
#endif
}

void clean_device_ram_qrfh_and_option(unsigned char rfmid)
{
#ifdef HUB_DEVICE
  if(rfmid == 0 || rfmid == 0xff ){
      return;
  }
  if(rfmid >= RFMID_EN_INDEX_IO_FIRST && rfmid <= RFMID_EN_INDEX_IO_LAST){
      ram_attr.IOen_lock[rfmid - 1] = 0;
  }
  ram_attr.qrfh1_buf[rfmid] = 0;
  ram_attr.qrfh2_buf[rfmid] = 0;
  set_qrfh_countdown(rfmid, 0); //调用了全片擦除接口，就不会调 setDeviceParam ENpbyNodeQrfH2First
  memset(ram_attr.opption_buf[rfmid], 0, OPTION_LENGTH);
#else
  (void)rfmid;
#endif
}

void set_qrfh_countdown(unsigned char rfmid, unsigned char countdown)
{
#ifdef HUB_DEVICE
  if(rfmid == 0 || rfmid == 0xff ){
      return;
  }
#if(0)
  if(!check_rfmid_is_registered(rfmid)){
      return;
  }
#endif
  qrfh_countdown[rfmid] = countdown;
#else
  (void)rfmid;
  (void)countdown;
#endif
}

unsigned char get_qrfh_countdown(unsigned char rfmid)
{
#ifdef HUB_DEVICE
  if(rfmid == 0 || rfmid == 0xff ){
      return 0;
  }
  return qrfh_countdown[rfmid];
#else
  (void)rfmid;
  return 0;
#endif
}

void update_rfm_qrfh_countdown(unsigned char rfmid)
{
#ifdef HUB_DEVICE
  if(rfmid == 0 || rfmid == 0xff ){
      return;
  }
  unsigned char qrfh2 = 0;
#if(0)
  if(!check_rfmid_is_registered(rfmid)){
      qrfh_countdown[rfmid] = 0;
      return;
  }
#endif
  if(qrfh_countdown[rfmid]){
      qrfh_countdown[rfmid]--;
      if(qrfh_countdown[rfmid] == 0){
          setDeviceParam(rfmid, ENpbyNodeQrfH2First, &qrfh2);
      }
  }
#else
  (void)rfmid;
#endif
}

void lock_rfm_join_pub(unsigned char rfmid)
{
#ifdef HUB_DEVICE
  unsigned char idx = (rfmid - 1)/8;
  unsigned char bit = (rfmid - 1)%8;
  bool log_enable = false;

  ram_attr.join_pub_lock[idx] |= (1 << bit);
  get_api_log_enable(HUB_API_LOG, &log_enable);
  if(log_enable){
      DS_app_log_hexdump_error("[join lock]",ram_attr.join_pub_lock,NODE_JOIN_PUB_LENGTH);
  }
#else
  (void)rfmid;
#endif
}

bool check_rfm_is_join_pub_lock(unsigned char rfmid)
{
#ifdef HUB_DEVICE
  unsigned char idx = (rfmid - 1)/8;
  unsigned char bit = (rfmid - 1)%8;
  bool log_enable = false;

  get_api_log_enable(HUB_API_LOG, &log_enable);
  if(log_enable){
      DS_app_log_hexdump_error("[check lock]",ram_attr.join_pub_lock,NODE_JOIN_PUB_LENGTH);
  }
  if(((ram_attr.join_pub_lock[idx] & (1 << bit)) >> bit)){
      return true;
  }
#else
  (void)rfmid;
#endif
  return false;
}
